﻿define("ow-epi-videocloud/BrowserViewModel", [
// dojo
        "dojo/_base/array",
        "dojo/_base/Deferred",
        "dojo/dom-attr",
// dijit
        "dijit/form/ToggleButton",
        "ow-epi-videocloud/knockout-2.2.1",
        "epi/shell/widget/SearchBox"
],
    function (array, Deferred, domAttr, ToggleButton, ko) {

        var getJSON = function (url, content) {
            var deferred = new Deferred();

            dojo.xhrGet({
                url: url,
                handleAs: "json",
                content: content,
                error: function (result) {
                    deferred.reject(result);
                },
                load: function (result) {
                    deferred.resolve(result);
                }
            });

            return deferred;
        };

        ko.bindingHandlers.prependText = {
            update: function (element, valueAccessor) {
                var value = valueAccessor();
                $(element).html(value() + $(element).html());
            }
        };

        ko.bindingHandlers.appendText = {
            update: function (element, valueAccessor) {
                var value = valueAccessor();
                if (value) {
                    value = ko.utils.unwrapObservable(value);
                    $(element).html($(element).html() + value);
                }
            }
        };

        ko.bindingHandlers.truncatedText = {
            update: function (element, valueAccessor, allBindingsAccessor) {
                var value = ko.utils.unwrapObservable(valueAccessor()),
                length = ko.utils.unwrapObservable(allBindingsAccessor().length) || ko.bindingHandlers.truncatedText.defaultLength,
                truncatedValue = value && value.length > length ? value.substring(0, Math.min(value.length, length)) + " ..." : value;

                ko.bindingHandlers.text.update(element, function () { return truncatedValue; });
            },
            defaultLength: 15
        };


        (function ($) {
            function debounce(callback, delay) {
                var self = this, timeout, _arguments;
                return function () {
                    _arguments = Array.prototype.slice.call(arguments, 0),
                    timeout = clearTimeout(timeout, _arguments),
                    timeout = setTimeout(function () {
                        callback.apply(self, _arguments);
                        timeout = 0;
                    }, delay);

                    return this;
                };
            }

            $.extend($.fn, {
                debounce: function (event, callback, delay) {
                    this.bind(event, debounce.apply(this, [callback, delay]));
                }
            });
        })(jQuery);

        ko.extenders.defaultIfNull = function (target, defaultValue) {
            var result = ko.computed({
                read: target,
                write: function (newValue) {
                    if (!newValue) {
                        target(defaultValue);
                    } else {
                        target(newValue);
                    }
                }
            });

            result(target());

            return result;
        };

        ko.bindingHandlers.dijitValue = {
            init: function (element, valueAccessor) {
                var _options = valueAccessor();

                var defaultOptions = {
                    useStandarWidget: true,
                    eventName: 'onChange',
                    getValueFunction: function (w) {
                        return w.value;
                    },
                    css: '',
                    settings: {}
                };

                var options = dojo.mixin({}, defaultOptions, _options);

                var widget;
                if (options.useStandarWidget) {
                    widget = new dijit.form[options.widget](options.settings);
                } else if (options.widget == 'epi.shell.widget.SearchBox') {
                    widget = new epi.shell.widget.SearchBox(options.settings);
                }

                widget = widget.placeAt(element);

                if (options.css) {
                    dojo.addClass(widget.domNode, options.css);
                }

                //respond to change event of the control
                dojo.connect(widget, options.eventName, function () {
                    var value = options.value;
                    if (ko.isWriteableObservable(value)) {
                        value(options.getValueFunction(widget));
                    }
                });
            },
            //respond to updates to the observable
            update: function (element, valueAccessor) {
                var options = valueAccessor();
                var widget = dijit.byNode(element.children[0]);
                if (widget) {
                    //widget.set("value", ko.utils.unwrapObservable(options.value));
                    widget.set("value", null);
                }
            }
        };

        ko.bindingHandlers.date = {
            init: function (element, valueAccessor) {
                try {
                    var jsonDate = ko.utils.unwrapObservable(valueAccessor());
                    var value = new Date(parseInt(jsonDate));
                    element.textContent = value.getDate() + "/" + value.getMonth() + 1 + "/" + value.getFullYear();
                }
                catch (exc) {
                }
                $(element).change(function () {
                    valueAccessor(element.textContent);
                });
            },
            update: function (element, valueAccessor) {
                valueAccessor(element.textContent);
            }
        };

        var InfiniteScrollViewModel = function (numberOfItemsInChunk) {
            var self = this;
            this.pageNumber = ko.observable().extend({ defaultIfNull: 0 });

            this.numberOfItemsInChunk = ko.observable().extend({ defaultIfNull: numberOfItemsInChunk });

            this.totalItemsCount = ko.observable().extend({ defaultIfNull: -1 });

            this.totalPages = ko.computed(function () {
                var division = self.totalItemsCount() / self.numberOfItemsInChunk();
                if (self.totalItemsCount() % self.numberOfItemsInChunk() === 0) {
                    return division;
                } else {
                    return Math.floor(division) + 1;
                }
            }, self);

            this.isEmpty = ko.computed(function () {
                return (self.totalItemsCount() > 0) === false;
            });

            this.goToNextPage = function () {
                if (self.canGoToNextPage() == false)
                    return;

                self.pageNumber(parseInt(self.pageNumber()) + 1);
            };

            this.canGoToNextPage = function () {
                return self.pageNumber() < self.totalPages();
            };
        };

        var VideoViewModel = function (data) {
            this.name = ko.observable(data.name);
            this.thumbnailUrl = ko.observable("url('" + data.thumbnailURL + "')");
            this.id = ko.observable(data.id);
            var date = new Date(parseInt(data.publishedDate));
            var dateString = date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear();
            this.publishedDate = ko.observable(dateString);
        };

        var BrowserViewModel = function (fileControllerUrl, selectedValues, players) {
            var self = this;
            this.browserWidget = null;

            this.players = ko.observableArray(players);
            this.selectedItem = ko.observable();
            this.selectedPlayer = ko.observable();

            this.infiniteScroll = new InfiniteScrollViewModel(12);

            this.videos = ko.observableArray();
            this.isLoading = ko.observable(false);
            this.phrase = ko.observable();

            this.selectedValue = ko.computed(function () {
                return {
                    selectedItem: self.selectedItem(),
                    selectedPlayer: self.selectedPlayer()
                };
            }, this);

            this.view = function (item) {
                self.selectedItem(item.id());
                self.browserWidget.selectedItem = JSON.stringify(self.selectedValue());
            };

            this.selectedPlayer.subscribe(function () {
                self.browserWidget.selectedItem = JSON.stringify(self.selectedValue());
            });

            this.infiniteScroll.pageNumber.subscribe(function () {
                if (self.infiniteScroll.pageNumber() > 0) {
                    self.getMoreResults();
                }
            });

            this.reset = function () {
                self.videos([]);
                self.infiniteScroll.pageNumber(0);
                self.infiniteScroll.totalItemsCount(-1);
            };

            this.phrase.subscribe(function () {
                self.isLoading(true);
                self.reset();
                self.getMoreResults();
            }, this);

            this.getMoreResults = function () {
                self.isLoading(true);
                return getJSON(fileControllerUrl + "/GetVideos", { phrase: self.phrase(), pageNumber: self.infiniteScroll.pageNumber() }).then(function (result) {
                    var items = $.map(result.items, function (item) { return new VideoViewModel(item); });
                    ko.utils.arrayForEach(items, function (item) {
                        if (self.selectedItem() !== item.id()) {
                            self.videos.push(item);
                        }
                    });

                    self.videos.valueHasMutated();
                    self.infiniteScroll.totalItemsCount(result.total_count);
                    self.isLoading(false);
                    $(".nano").nanoScroller({ alwaysVisible: true });
                });
            };

            self.isLoading(true);

            if (selectedValues) {
                var values = JSON.parse(selectedValues);
                self.selectedItem(values.selectedItem);
                self.selectedPlayer(values.selectedPlayer);

                getJSON(fileControllerUrl + "/GetVideo", { videoId: self.selectedItem() }).then(function (selectedVideo) {
                    var video = new VideoViewModel(selectedVideo);
                    self.videos.unshift(video);
                });
            }

            getJSON(fileControllerUrl + "/GetVideos", { phrase: self.phrase(), pageNumber: self.infiniteScroll.pageNumber() }).then(function (result) {
                ko.utils.arrayForEach($.map(result.items, function (item) { return new VideoViewModel(item); }), function (item) {
                    if (self.selectedItem() !== item.id()) {
                        self.videos.push(item);
                    }
                });

                self.infiniteScroll.totalItemsCount(result.total_count);
                $(".nano").debounce("scrollend", function () {
                    self.infiniteScroll.goToNextPage();
                }, 50);
                $(".nano").nanoScroller({ alwaysVisible: true });

                self.isLoading(false);
            });
        };

        return BrowserViewModel;
    });